package cn.dapeng.rpc.common.util;

import cn.dapeng.rpc.common.exception.InvalidMagicNumException;

public class MagicNumberUtil {

    public static void main(String[] args) {
        int num = getMagic(1, 128, 60000, 0, 0);

        System.out.println(getVersion(num));
        System.out.println(getHeaderLen(num));
        System.out.println(getBodyLen(num));
        System.out.println(getSerialVersion(num));
        System.out.println(getRequestType(num));
        decodec(num);
    }

    /**
     * 1.前四位是版本号
     * 2.第五位至第十二位是header长度
     * 3.第十三位到二十八位是body长度*
     * 4.第二十九位和三十位是序列化工具选择
     * 5.第三十一位代表是请求还是响应类型
     *
     * @param version       :   当前的版本号
     * @param headerLen     :   header长度
     * @param bodyLen       :   body长度
     * @param serialVersion :   序列化枚举
     * @param requestType   :   0 请求，1 响应
     * @return
     * @see cn.dapeng.rpc.common.RequestTypeEnum
     */
    public static int getMagic(int version, int headerLen, int bodyLen, int serialVersion, int requestType) {
        int t = version | (headerLen << 4) | (bodyLen << 12) | (serialVersion << 28) | (requestType << 30);
        if (t < 0)
            throw new InvalidMagicNumException(t);
        return t;
    }

    public static int getVersion(int num) {
        return num & 0xf;
    }

    public static int getHeaderLen(int num) {
        return (num & 0xff0) >> 4;
    }

    public static int getBodyLen(int num) {
        return (num & 0xffff000) >> 12;
    }

    public static int getSerialVersion(int num) {
        return (num & 0x30000000) >> 28;
    }

    public static int getRequestType(int num) {
        return (num & 0x40000000) >> 30;
    }

    public static void decodec(int num) {
        System.out.println("版本：" + (num & 0xf));
        System.out.println("headerLen:" + ((num & 0xff0) >> 4));
        System.out.println("bodyLen:" + ((num & 0xffff000) >> 12));
        System.out.println("serialVersion:" + ((num & 0x30000000) >> 28));
        System.out.println("requestType:" + ((num & 0x40000000) >> 30));
    }

}
